﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

using Db4o.Framework.Interfaces;

namespace Db4o.Framework.Business
{
    public class BusinessManager : ILogged
    {
        #region Design pattern : << Singleton BusinessManager >>

        // read-only private member
        private static readonly BusinessManager instance = new BusinessManager();

	    // private construtor
        private BusinessManager() { }

	    // public property
        public static BusinessManager Instance { get { return instance; } }

        #endregion

        private Assembly mBusinessAssembly;
        private List<Type> mManagedTypes;

        #region Properties
        /// <summary>
        /// Property that contain the Business assembly to manage
        /// </summary>
        internal Assembly BusinessAssembly
        {
            get { return mBusinessAssembly; }
            set 
            {
                if(CheckManagedEntities(value) == false)
                    ExceptionManager.Instance.ThrowFatalLogException("UnManagedTypeException", "No managed entities was found, verify classes declaration");          
                else
                    mBusinessAssembly = value;
            }
        }
        /// <summary>
        /// Return the assembly name
        /// </summary>
        public string AssemblyName
        {
            get { return BusinessManager.Instance.BusinessAssembly != null ? BusinessManager.Instance.BusinessAssembly.GetName().Name : null; }
        }
        /// <summary>
        /// List of managed types
        /// </summary>
        public List<Type> ManagedTypes
        {
            get { return mManagedTypes; }
        }

        #endregion

        /// <summary>
        /// Check in the specified assembly all the managed entities
        /// </summary>
        /// <returns></returns>
        private bool CheckManagedEntities(Assembly assembly)
        {
            bool contains = false;
            mManagedTypes = new List<Type>();

            try
            {
                foreach (Type type in assembly.GetTypes())
                    if (type.IsSubclassOf(typeof(ManagedType)))
                    {
                        mManagedTypes.Add(type);
                        contains = true;
                    }
            }
            catch (ReflectionTypeLoadException e)
            {
                ExceptionManager.Instance.ThrowFatalLogException("system", "Assembly was not found", e);
            }
            
            return contains;
        }
        /// <summary>
        /// Get the type specified in parameter
        /// </summary>
        /// <param name="typeName">name of the type</param>
        /// <returns>Type :)</returns>
        public Type GetType(string typeName)
        {
            try
            {
                return BusinessAssembly.GetType(AssemblyName + "." + typeName);
            }
            catch (Exception e) { throw e; }
        }
     
    }
}
